﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using nanoCMS.Core.Concrete;
using nanoCMS.Core.Membership;

namespace nanoCMS.Core.Providers {
	public class ModuleProvider {
		private readonly Entities entities;
		private readonly CacheProvider cacheProvider = CacheProvider.Default;
		private UserRoleProvider _userRoleProvider;

		private UserRoleProvider userRoleProvider { get { return _userRoleProvider ?? (_userRoleProvider = new UserRoleProvider(entities)); } }

		private const string modulesCacheKey = "modules";
		public ModuleProvider(Entities entities) {
			this.entities = entities;
		}

		#region Modules
		private List<Module> Modules {
			get {
				if (cacheProvider.Contains(modulesCacheKey))
					return cacheProvider.Get(modulesCacheKey) as List<Module>;

				List<Module> modules = entities.Modules.ToList();
				cacheProvider.Add(modulesCacheKey, modules, new CacheItemPolicy { SlidingExpiration = new TimeSpan(0, 0, 30, 0) });
				return modules;
			}
			set {
				if (cacheProvider.Contains(modulesCacheKey)) cacheProvider.Remove(modulesCacheKey);
				cacheProvider.Add(modulesCacheKey, value, new CacheItemPolicy { SlidingExpiration = new TimeSpan(0, 0, 30, 0) });
			}
		}


		/// <summary>
		/// Registers module in system
		/// </summary>
		/// <param name="moduleName"></param>
		/// <param name="filePath"></param>
		/// <returns></returns>
		public int RegisterModule(string moduleName, string filePath = null) {
			if (entities.Modules.Any(x => x.ModuleName == moduleName)) return -1;

			Module module = new Module {
				ModuleName = moduleName,
				FilePath = filePath
			};

			entities.Modules.AddObject(module);
			entities.SaveChanges();

			var modules = Modules;
			modules.Add(module);
			Modules = modules;

			return module.ModuleID;
		}

		public Module GetModule(int moduleID) {
			var module = Modules.SingleOrDefault(x => x.ModuleID == moduleID);
			if (module == null) throw new ArgumentException("No module with a ID:" + moduleID);
			return module;
		}

		public Module GetModule(string moduleName) {
			var module = Modules.SingleOrDefault(x => x.ModuleName == moduleName);
			if (module == null) throw new ArgumentException("No module with a name:" + moduleName);
			return module;
		}

		#endregion

		#region Module Actions

		


		//public int RegisterModuleAction(string moduleName, string actionName) {
		//   var module = GetModule(moduleName);

		//   if (entities.ModuleActions.Any(x => x.ModuleID == module.ModuleID && x.ActionName == actionName)) return -1;

		//   var moduleAction = new ModuleAction {
		//      ModuleID = module.ModuleID,
		//      ActionName = actionName
		//   };

		//   entities.ModuleActions.AddObject(moduleAction);
		//   entities.SaveChanges();
		//   return moduleAction.ModuleActionID;
		//}


		//public void EditRolesForAction(int moduleActionID, List<int> newRoles) {
		//   var currentRoles = GetModuleAction(moduleActionID).UserRoles.Select(x => x.RoleID).ToList();

		//   //if current role is not in newRoles
		//   foreach (var currentRole in currentRoles.Where(currentRole => !newRoles.Contains(currentRole))) {
		//      currentRoles.Remove(currentRole);
		//   }

		//   //if newRoles contain role witch is not in current roles
		//   foreach (var newRole in newRoles.Where(newRole => !currentRoles.Contains(newRole))) {
		//      currentRoles.Add(newRole);
		//   }
		//   entities.SaveChanges();
		//}

		//public ModuleAction GetModuleAction(string moduleName, string actionName)
		//{
		//   var module = GetModule(moduleName);
		//   var moduleAction =
		//      entities.ModuleActions.SingleOrDefault(x => x.ActionName == actionName && x.ModuleID == module.ModuleID);
		//   if (moduleAction == null) throw new ArgumentException("There is no actionName with name:" + actionName + " in module name " + moduleName);
		//   return moduleAction;
		//}

		//private ModuleAction GetModuleAction(int moduleActionID) {
		//   var moduleAction = entities.ModuleActions.SingleOrDefault(x => x.ModuleActionID == moduleActionID);
		//   if (moduleAction == null) throw new ArgumentOutOfRangeException("There is no moduleActionID: " + moduleActionID);
		//   return moduleAction;
		//}


		//public List<int> GetRolesForAction(int moduleActionID) {
		//   return GetModuleAction(moduleActionID).UserRoles.Select(x => x.RoleID).ToList();
		//}

		//#region Overloads
		//public void EditRolesForAction(int moduleActionID, string[] newRoles) {
		//   List<int> roles = newRoles.Select(newRole => userRoleProvider.GetRoleID(newRole)).ToList();
		//   EditRolesForAction(moduleActionID, roles);
		//}
		//#endregion

		#endregion
	}
}
